﻿using System;
using System.Collections.ObjectModel;
using System.Windows.Input;
using System.Windows.Threading;
using Majoopic.Engine;
using Majoopic.WPFClient.Commands;
using Winforms = System.Windows.Forms;

namespace Majoopic.WPFClient.ViewModels
{
    /// <summary>
    /// 
    /// </summary>
    public class EngineManagerViewModel : BaseViewModel
    {
        private FileEngine _currentJob
        {
            get
            {
                return Mediator.Current.CurrentFileEngine;
            }
            set
            {
                Mediator.Current.CurrentFileEngine = value;
            }
        }

        private ProgressInformation _ProgressInformation;
        public ProgressInformation ProgressInformation
        {
            get
            {
                return this._ProgressInformation;
            }
            set
            {
                this._ProgressInformation = value;
                this.OnPropertyChanged("ProgressInformation");
            }
        }

        private string _ScanDirectoryTime;
        public string ScanDirectoryTime
        {
            get
            {
                return this._ScanDirectoryTime;
            }
            set
            {
                this._ScanDirectoryTime = value;
                this.OnPropertyChanged("ScanDirectoryTime");
            }
        }

        private string _RootFolderText;
        /// <summary>
        /// 
        /// </summary>
        public string RootFolderText
        {
            get
            {
                return this._RootFolderText;
            }
            set
            {
                if (this._RootFolderText != value)
                {
                    this._RootFolderText = value;
                    this.OnPropertyChanged("RootFolderText");
                    CommandHelper.RaiseCommandCanExecuteChanged(this.StartJobCommand);
                }
            }
        }


        private bool _WithMessages;
        /// <summary>
        /// 
        /// </summary>
        public bool WithMessages
        {
            get
            {
                return this._WithMessages;
            }
            set
            {
                if (this._WithMessages != value)
                {
                    this._WithMessages = value;
                    this.OnPropertyChanged("WithMessages");
                }
            }
        }



        private bool _WithCounters;
        /// <summary>
        /// 
        /// </summary>
        public bool WithCounters
        {
            get
            {
                return this._WithCounters;
            }
            set
            {
                if (this._WithCounters != value)
                {
                    this._WithCounters = value;
                    this.OnPropertyChanged("WithCounters");
                }
            }
        }


        private bool _IsScanButtonVisible;
        /// <summary>
        /// 
        /// </summary>
        public bool IsScanButtonVisible
        {
            get
            {
                return this._IsScanButtonVisible;
            }
            set
            {
                if (this._IsScanButtonVisible != value)
                {
                    this._IsScanButtonVisible = value;
                    this.OnPropertyChanged("IsScanButtonVisible");
                }
            }
        }
        
        ///// <summary>
        ///// 
        ///// </summary>
        //public bool IsCancelButtonVisible
        //{
        //    get
        //    {
        //        return !this.IsScanButtonVisible;
        //    }
        //}


        private bool _IsScanDirectory;
        /// <summary>
        /// 
        /// </summary>
        public bool IsScanDirectory
        {
            get
            {
                return this._IsScanDirectory;
            }
            set
            {
                if (this._IsScanDirectory != value)
                {
                    this._IsScanDirectory = value;
                    this.OnPropertyChanged("IsScanDirectory");
                }
            }
        }
        
        private bool _isCancelling;

        /* private void OnPropertyChanged(string propertyName)
         {
             if(this.PropertyChanged!=null)
             {
                 this.PropertyChanged(this,new PropertyChangedEventArgs(propertyName));
             }
         }

         private string _TotalImagesFound;
         public string TotalImagesFound
         {
             get
             {
                 return this._TotalImagesFound;
             }
             private set
             {
                 if(string.Equals(this._TotalImagesFound,value) == false)
                 {
                     this._TotalImagesFound = value;
                     this.OnPropertyChanged("TotalImagesFound");
                 }
             }
         }

         private string _ImagesScaned;
         public string ImagesScaned
         {
             get
             {
                 return this._ImagesScaned;
             }
             private set
             {
                 if(string.Equals(this._ImagesScaned,value) == false)
                 {
                     this._ImagesScaned = value;
                     this.OnPropertyChanged("ImagesScaned");
                 }
             }
         }*/
        


        

        public ObservableCollection<Message> Messages
        {
            get;
            set;
        }

        /// <summary>
        /// 
        /// </summary>
        public ICommand StartJobCommand
        {
            get;
            private set;
        }

        public ICommand SelectFolderCommand
        {
            get;
            private set;
        }

        public ICommand CancelJobCommand
        {
            get;
            private set;
        }

        /// <summary>
        /// Constructor
        /// </summary>
        public EngineManagerViewModel()
            : base()
        {
            //this.ScanObject = new RoutedCommand()
            this.IsScanButtonVisible = true;
            this.WithMessages = true;
            this.WithCounters = true;
            this.Messages = new ObservableCollection<Message>();
            this.StartJobCommand = new GenericCommand(x => this.BeginJob(), x => { return System.IO.Directory.Exists(this.RootFolderText); });
            this.CancelJobCommand = new GenericCommand(x => this.CancelJob(), x => { return !this._isCancelling; });
            this.SelectFolderCommand = new GenericCommand(x => this.SelectFolder(), x => { return this._currentJob == null; });
        }

        private void BeginJob()
        {
            if (this._currentJob == null)
            {
                this._isCancelling = false;
                try
                {
                    this._currentJob = new FileEngine(this.CurrentServiceContext, this.RootFolderText, true);
                    if (this.WithMessages)
                        this._currentJob.MessageAdded += new EventHandler<MessageEventArgs>(_currentJob_MessageAdded);
                    this._currentJob.TaskFinished += new EventHandler(_currentJob_TaskFinished);
                    this._currentJob.ScanDirectoryFinished += new EventHandler(_currentJob_ScanDirectoryFinished);
                    this.Messages.Clear();
                    this.IsScanButtonVisible = false;
                    this.IsScanDirectory = true;
                    //this.btScan.Content = "Cancel";
                    //this.pBarScanDirectory.Value = 0;
                    if (this.WithCounters)
                        this.ProgressInformation = new ProgressInformation();
                    else
                        this.ProgressInformation = null;
                    //this.pBarScanDirectory.IsIndeterminate = true;
                    this._currentJob.StartAsyncJob(this.ProgressInformation);
                }
                catch (Exception ex)
                {
                    this.AddMessage(new Message(MessageType.Error, string.Format("Error when starting the job. Exception : {0}", ex.ToString()), ex));
                }
            }            
        }

        private void CancelJob()
        {
            if (this._currentJob != null)
            {
                this._currentJob.Cancel();
            }
            else
            {
                // Just in case ... but no reason to passe here or there is a problem
                // If cancelButton is visible, a job is running, otherwise CancelButton is not visible so CancelJob can't be called
                this.IsScanButtonVisible = true;
            }
        }


        private void _currentJob_ScanDirectoryFinished(object sender, EventArgs e)
        {
            this.UIDispatcher.Invoke(new Action(this.ScanDirectoryFinished), DispatcherPriority.Background);
        }

        private void ScanDirectoryFinished()
        {
            this.IsScanDirectory = false;
        }

        private void _currentJob_TaskFinished(object sender, EventArgs e)
        {
            this._currentJob.MessageAdded -= _currentJob_MessageAdded;
            this._currentJob.TaskFinished -= _currentJob_TaskFinished;
            this._currentJob = null;
            this._isCancelling = false;
            this.IsScanButtonVisible = true;
        }

        private void _currentJob_MessageAdded(object sender, MessageEventArgs e)
        {
            this.AddMessage(e.Message);
        }

        private void AddMessage(Message message)
        {
            if (!this.UIDispatcher.CheckAccess())
            {
                this.UIDispatcher.BeginInvoke(new Action(() => this.AddMessage(message)), DispatcherPriority.Input);
            }
            else
            {
                this.Messages.Add(message);
                //this.tbMessage.Text += message.Value + "\n";
                /*if (message.Type == MessageType.Error)
                {
                    textToAdd.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Red);
                }
                this.richTBMessages.AppendText(textToAdd.Text);   */
            }
        }

        private void SelectFolder()
        {
            Winforms.FolderBrowserDialog folderBrowser = new Winforms.FolderBrowserDialog();
            if (folderBrowser.ShowDialog() == Winforms.DialogResult.OK)
            {
                this.RootFolderText = folderBrowser.SelectedPath;
            }
        }
    }
}
